/**
 * 
 */
package com.effectiv.req1.controller;

import java.util.ArrayList;
import java.util.Collections;
import java.util.Date;

import java.util.List;

import javax.validation.Valid;

import lombok.extern.slf4j.Slf4j;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.mongodb.core.MongoTemplate;
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.validation.BindingResult;

import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.ResponseBody;
import com.effectiv.req1.domain.Flow;
import com.effectiv.req1.domain.Project;
import com.effectiv.req1.domain.Step;
import com.effectiv.req1.domain.UseCase;
import com.effectiv.req1.domain.User;
import com.effectiv.req1.repository.ProjectRepository;
import com.effectiv.req1.repository.UseCaseRepository;
import com.effectiv.req1.security.SecurityUtil;


/**
 * @author Dhrubo
 * 
 */
@Controller
@Slf4j
public class UseCaseController {

	@Autowired
	private UseCaseRepository useCaseRepository;
	@Autowired
	private ProjectRepository projectRepository;
	
	@Autowired
	private MongoTemplate mongoTemplate;

	@RequestMapping(value = "/listusecases")
	public final String showHome(Model model) {

		model.addAttribute("useCases", useCaseRepository.findAll());

		return "listusecases";
	}

	@RequestMapping(value = "/newusecase")
	public final String newUseCaseDisplay(Model model) {

		UseCase useCase = new UseCase();
		model.addAttribute(useCase);
		
		User user = SecurityUtil.getUserDetails();
		
		List<Project> projects = null;
		
		log.info("Projects == {}", projects);
		
		model.addAttribute("projects", projects);

		return "newusecase";
	}

	@RequestMapping(value = "/saveusecase", method = RequestMethod.POST)
	public final String save(@Valid UseCase useCase, BindingResult result) {
		log.info("Result = {}", result);

		if (!result.hasErrors()) {

			Date timestamp = new Date();

			useCase.setCreatedDate(timestamp);
			useCase.setLastUpdatedDate(timestamp);

			useCase.setCreatedBy(SecurityUtil.getUserDetails());
			useCase.setLastUpdatedBy(SecurityUtil.getUserDetails());
			useCase.setCompany(SecurityUtil.getUserDetails().getCompany());

			useCase.setMainFlow(new Flow());

			useCaseRepository.save(useCase);
		}

		return "newusecase";
	}

	@RequestMapping(value = "/editusecase")
	public final String editUseCaseDisplay(
			@RequestParam(value = "usecase", required = true) String id,
			@RequestParam(value = "active", required = true, defaultValue = "1") int active,
			Model model) {

		UseCase useCase = useCaseRepository.findOne(id);
		model.addAttribute(useCase);
		model.addAttribute("active", active);
		return "editusecase";
	}

	@RequestMapping(value = "/updateusecase")
	public final String updateUseCaseDisplay(@Valid UseCase useCase,
			BindingResult result, Model model) {

		UseCase useCaseTarget = useCaseRepository.findOne(useCase.getId());

		useCaseTarget.setDescription(useCase.getDescription());
		useCaseTarget.setName(useCase.getName());
		useCaseTarget.setLastUpdatedBy(SecurityUtil.getUserDetails());
		useCaseTarget.setLastUpdatedDate(new Date());

		useCaseRepository.save(useCaseTarget);

		model.addAttribute(useCaseTarget);
		model.addAttribute("active", 1);
		return "redirect:editusecase?usecase=" + useCase.getId() + "&active=1";
	}

	@RequestMapping(value = "/viewusecase")
	public final String viewUseCase(
			@RequestParam(value = "usecase", required = true) String id,
			Model model) {

		UseCase useCase = useCaseRepository.findOne(id);
		model.addAttribute(useCase);

		return "viewusecase";
	}

	@RequestMapping(value = "/updatemainflow")
	public @ResponseBody
	String editUseCaseMainFlowStepDescription(@RequestParam("pk") String id,
			@RequestParam("name") String rowNum,
			@RequestParam("value") String value) {

		log.info("Use case id = {}", id);
		log.info("Row num id = {}", rowNum);

		log.info("Row value = {}", value);

		UseCase useCase = useCaseRepository.findOne(id);

		return "editusecase";
	}

	@RequestMapping(value = "/addmainflow")
	public String addUseCaseMainFlowStepDescription(
			@RequestParam("id") String id, @RequestParam("step") String step,
			Model model) {

		log.info("Use case id = {}", id);
		log.info("Row num id = {}", step);

		UseCase useCase = useCaseRepository.findOne(id);

		List<Step> steps = useCase.getMainFlow().getSteps();

		if (steps == null) {
			steps = new ArrayList<Step>();
		}

		Step stepN = new Step();
		stepN.setDescription(step);
		steps.add(stepN);

		useCase.getMainFlow().setSteps(steps);

		useCaseRepository.save(useCase);

		return "redirect:editusecase?usecase=" + id + "&active=6";
	}

	@RequestMapping(value = "/moveup")
	public String moveUp(@RequestParam("usecase") String id,
			@RequestParam("index") int index, Model model) {
		log.info("Use case id = {}", id);
		log.info("Row num id = {}", index);

		UseCase useCase = useCaseRepository.findOne(id);

		List<Step> steps = useCase.getMainFlow().getSteps();

		Collections.swap(steps, index - 1, index);

		useCase.getMainFlow().setSteps(steps);

		useCaseRepository.save(useCase);

		return "redirect:editusecase?usecase=" + id + "&active=7";
	}

	@RequestMapping(value = "/movedown")
	public String moveDown(@RequestParam("usecase") String id,
			@RequestParam("index") int index, Model model) {
		log.info("Use case id = {}", id);
		log.info("Row num id = {}", index);

		UseCase useCase = useCaseRepository.findOne(id);

		List<Step> steps = useCase.getMainFlow().getSteps();

		Collections.swap(steps, index, index + 1);

		useCase.getMainFlow().setSteps(steps);

		useCaseRepository.save(useCase);

		return "redirect:editusecase?usecase=" + id + "&active=7";
	}

	@RequestMapping(value = "/deleteucstep")
	public String delete(@RequestParam("usecase") String id,
			@RequestParam("index") int index, Model model) {
		log.info("Use case id = {}", id);
		log.info("Row num id = {}", index);

		UseCase useCase = useCaseRepository.findOne(id);

		List<Step> steps = useCase.getMainFlow().getSteps();

		steps.remove(index);

		useCase.getMainFlow().setSteps(steps);

		useCaseRepository.save(useCase);

		return "redirect:editusecase?usecase=" + id + "&active=7";
	}

	@RequestMapping(value = "/newalternate")
	public String newAlternate(@RequestParam("usecase") String id,
			@RequestParam("index") int index, Model model) {
		log.info("Use case id = {}", id);
		log.info("Row num id = {}", index);

		UseCase useCase = useCaseRepository.findOne(id);

		Flow flow = new Flow();
		flow.setAlternate(true);
		flow.setCreatedBy(SecurityUtil.getUserDetails());
		flow.setLastUpdatedBy(SecurityUtil.getUserDetails());

		Date timestamp = new Date();
		flow.setCreatedDate(timestamp);
		flow.setLastUpdatedDate(timestamp);

		List<Step> steps = useCase.getMainFlow().getSteps();

		Step step = steps.get(index);

		List<Flow> alternates = step.getAlternates();

		if (alternates == null) {
			alternates = new ArrayList<Flow>();
		}

		alternates.add(flow);
		step.setAlternates(alternates);

		useCase.getMainFlow().setSteps(steps);

		useCaseRepository.save(useCase);

		return "redirect:editusecase?usecase=" + id + "&active=7";
	}

	@RequestMapping(value = "/addalternateflowstep")
	public String addAlternateFlow(
			@RequestParam("description") String description,
			@RequestParam("id") String id, @RequestParam("stepid") int stepid,
			@RequestParam("flowid") int flowid, Model model) {
		log.info("description = {}", description);
		log.info("id = {}", id);
		log.info("stepid = {}", stepid);
		log.info("flowid = {}", flowid);

		UseCase useCase = useCaseRepository.findOne(id);

		Flow alternateFlow = useCase.getMainFlow().getSteps().get(stepid)
				.getAlternates().get(flowid);

		List<Step> altFlowSteps = alternateFlow.getSteps();

		if (altFlowSteps == null) {
			altFlowSteps = new ArrayList<Step>();
		}

		Step stepN = new Step();
		stepN.setDescription(description);
		altFlowSteps.add(stepN);

		alternateFlow.setSteps(altFlowSteps);

		useCaseRepository.save(useCase);

		return "redirect:editusecase?usecase=" + id + "&active=7#alt" + stepid
				+ flowid;

	}

	@RequestMapping(value = "/moveupalternate")
	public String moveUpAlternate(@RequestParam("usecase") String id,
			@RequestParam("index") int index,
			@RequestParam("flowid") int flowid,
			@RequestParam("stepid") int stepid, Model model) {
		log.info("Use case id = {}", id);
		log.info("Row num id = {}", index);

		UseCase useCase = useCaseRepository.findOne(id);

		Flow alternateFlow = useCase.getMainFlow().getSteps().get(stepid)
				.getAlternates().get(flowid);

		List<Step> altFlowSteps = alternateFlow.getSteps();

		Collections.swap(altFlowSteps, index - 1, index);

		alternateFlow.setSteps(altFlowSteps);

		useCaseRepository.save(useCase);

		return "redirect:editusecase?usecase=" + id + "&active=7#alt" + stepid
				+ flowid;
	}

	@RequestMapping(value = "/movedownalternate")
	public String moveDownlternate(@RequestParam("usecase") String id,
			@RequestParam("index") int index,
			@RequestParam("flowid") int flowid,
			@RequestParam("stepid") int stepid, Model model) {
		log.info("Use case id = {}", id);
		log.info("Row num id = {}", index);

		UseCase useCase = useCaseRepository.findOne(id);

		Flow alternateFlow = useCase.getMainFlow().getSteps().get(stepid)
				.getAlternates().get(flowid);

		List<Step> altFlowSteps = alternateFlow.getSteps();

		Collections.swap(altFlowSteps, index, index - 1);

		alternateFlow.setSteps(altFlowSteps);

		useCaseRepository.save(useCase);

		return "redirect:editusecase?usecase=" + id + "&active=7#alt" + stepid
				+ flowid;
	}

	@RequestMapping(value = "/deletestepalternate")
	public String deleteStepAlternate(@RequestParam("usecase") String id,
			@RequestParam("index") int index,
			@RequestParam("flowid") int flowid,
			@RequestParam("stepid") int stepid, Model model) {
		log.info("Use case id = {}", id);
		log.info("Row num id = {}", index);

		UseCase useCase = useCaseRepository.findOne(id);

		Flow alternateFlow = useCase.getMainFlow().getSteps().get(stepid)
				.getAlternates().get(flowid);

		List<Step> altFlowSteps = alternateFlow.getSteps();

		altFlowSteps.remove(index);

		alternateFlow.setSteps(altFlowSteps);

		useCaseRepository.save(useCase);

		return "redirect:editusecase?usecase=" + id + "&active=7#alt" + stepid
				+ flowid;
	}

	@RequestMapping(value = "/addprecondition")
	public String addPreCondition(@RequestParam("usecase") String id,
			@RequestParam("description") String description, Model model) {

		UseCase useCase = useCaseRepository.findOne(id);
		List<String> preConditions = useCase.getPreConditions();

		if (preConditions == null) {
			preConditions = new ArrayList<String>();
		}

		preConditions.add(description);

		useCase.setPreConditions(preConditions);

		useCaseRepository.save(useCase);

		return "redirect:editusecase?usecase=" + id + "&active=3";
	}

	@RequestMapping(value = "/addpostcondition")
	public String addPostCondition(@RequestParam("usecase") String id,
			@RequestParam("description") String description, Model model) {

		UseCase useCase = useCaseRepository.findOne(id);
		List<String> postConditions = useCase.getPostConditions();

		if (postConditions == null) {
			postConditions = new ArrayList<String>();
		}

		postConditions.add(description);

		useCase.setPostConditions(postConditions);

		useCaseRepository.save(useCase);

		return "redirect:editusecase?usecase=" + id + "&active=3";
	}
}
